﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using crm_library.DataAccess.TableReps;
using System.Web.UI.WebControls;
using System.Web;
using System.Web.UI;
using crm_library.Javascript;
using System.Reflection;
using crm_library.DataAccess.ObjectReps;

namespace crm_library.Controls
{
	public class ListingTableBuilder<T> : UserControl where T : ObjectRepresentation, new()
	{
		#region buttons
		public class ExtraButton
		{
			private string _headerLabel { get; set; }
			private string _text { get; set; }
			private string _commandName { get; set; }
			private CommandEventHandler _handler { get; set; }

			public ExtraButton(string headerLabel, string text, string commandName, CommandEventHandler handler)
			{
				_headerLabel = headerLabel;
				_text = text;
				_commandName = commandName;
				_handler = handler;
			}

			public Button GenerateExtraButton(int pk)
			{
				return ListingTableBuilder<T>.GenerateButton(_text, _commandName, pk, _handler);
			}

			public string HeaderLabel { get { return _headerLabel; } }
		}
		private enum CommandTypes
		{
			Create,
			Edit,
			Delete
		}

		bool _hasCreatePermission;
		bool _hasViewPermission;
		bool _hasEditPermission;
		bool _hasDeletePermission;
		private Button _createBtn;
		private Button _filterBtn;
		private List<ExtraButton> _extraControls;
		public void AddExtraButton(string headerLabel, string text, string commandName, CommandEventHandler handler)
		{
			_extraControls.Add(new ExtraButton(headerLabel, text, commandName, handler));
		}
		private static Button GenerateButton(string text, string commandName, int pk, CommandEventHandler handler)
		{
			var btn = new Button
			{
				Text = text,
				CommandName = commandName,
				CommandArgument = pk.ToString()
			};
			btn.Command += handler;
			return btn;
		}
		private Button GenerateCreateButton()
		{
			return GenerateButton("Create", "Create", -1, ButtonClick);
		}
		private Button GenerateViewButton(int pk)
		{
			return GenerateButton("View", "View", pk, ButtonClick);
		}
		private Button GenerateEditButton(int pk)
		{
			return GenerateButton("Edit", "Edit", pk, ButtonClick);
		}
		private Button GenerateDeleteButton(int pk)
		{
			return GenerateButton("Delete", "Delete", pk, ButtonClick);
		}
		private Button GenerateFilterButton()
		{
			return GenerateButton("Filter", "Filter", -1, ButtonClick);
		}
		public void ButtonClick(object sender, CommandEventArgs e)
		{
			const string formatString = "/DataPages/{0}";

			if (e.CommandName.Equals("Filter"))
			{
				return;
			}
			else if (e.CommandName.Equals("Create"))
			{
				HttpContext.Current.Response.Redirect(String.Format(formatString, new T().GetCreatePageName()));
			}
			else if (e.CommandName.Equals("View"))
			{
				Session["Selection"] = e.CommandArgument.ToString();
				HttpContext.Current.Response.Redirect(String.Format(formatString, new T().GetViewPageName()));
			}
			else if (e.CommandName.Equals("Edit"))
			{
				Session["Selection"] = e.CommandArgument.ToString();
				HttpContext.Current.Response.Redirect(String.Format(formatString, new T().GetEditPageName()));
			}
			else if (e.CommandName.Equals("Delete"))
			{
				try
				{
					var record = new T();
					record.Load(int.Parse(e.CommandArgument.ToString()));
					record.Delete();
					Alert.Show("Record Deleted", Alert.AlertMessageType.Message);
					HttpContext.Current.Response.Redirect(HttpContext.Current.Request.Path);
				}
				catch (Exception ex)
				{
					Alert.Show("Error: cannot Delete:" + ex.Message, Alert.AlertMessageType.Error);
				}
			}
		}

		#endregion buttons

		#region filters
		private List<ListingTableFilter<T>> _filters;

		public List<ListingTableFilter<T>> GenerateFilters()
		{
			var source = new T();
			var propertyInfoList = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.Instance).ToList();
			_filters = new List<ListingTableFilter<T>>();

			foreach (var property in propertyInfoList)
			{
				var attributes = (ListingFieldAttribute[])property.GetCustomAttributes(typeof(ListingFieldAttribute), true);

				if (!attributes.Any()) continue;

				string columnName = property.Name;
				string displayText;

				if (!String.IsNullOrWhiteSpace(attributes[0].DisplayText)) displayText = attributes[0].DisplayText;
				else displayText = property.Name;

				ListingTableFilter<T>.ListingTableFilterType filterType;

				if (property.PropertyType.Equals(typeof(DateTime)))
				{
					filterType = ListingTableFilter<T>.ListingTableFilterType.TextBox;
				}
				else if (property.PropertyType.Equals(typeof(Enum)))
				{
					filterType = ListingTableFilter<T>.ListingTableFilterType.DropDownList;
				}
				else
				{
					filterType = ListingTableFilter<T>.ListingTableFilterType.TextBox;
				}


				_filters.Add(new ListingTableFilter<T>(columnName, displayText, filterType));
			}

			return _filters;
		}
		#endregion filters

		#region contents

		private Table _table;
		private List<T> _list;
		public List<T> Items
		{
			get
			{
				if (_list == null) _list = new List<T>();
				return _list;
			}
			set
			{
				_list = value;
			}
		}


		#endregion contents

		#region constructors

		public ListingTableBuilder(bool hasCreatePermission, bool hasViewPermission, bool hasEditPermission, bool hasDeletePermission, List<T> list)
		{
			_extraControls = new List<ExtraButton>();

			_createBtn = GenerateCreateButton();
			_filterBtn = GenerateFilterButton();

			_hasCreatePermission = hasCreatePermission;
			_hasViewPermission = hasViewPermission;
			_hasEditPermission = hasEditPermission;
			_hasDeletePermission = hasDeletePermission;
			_list = list;
		}

		#endregion constructors

		#region buildTable
		protected override void CreateChildControls()
		{
			base.CreateChildControls();

			var buttonPane = new Panel
			{
				CssClass = "ButtonPanel"
			};
			buttonPane.Controls.Add(_filterBtn);
			if (_hasCreatePermission) buttonPane.Controls.Add(_createBtn);

			Controls.Add(buttonPane);


			BuildTable(Items);
			Controls.Add(_table);
		}

		private void BuildTable(List<T> list)
		{
			_table = new Table();

			_table.ID = "sortMe";
			_table.ClientIDMode = System.Web.UI.ClientIDMode.Static;
			_table.CssClass = "SortableTable tablesorter";

			_table.Rows.Add(GenHeaderRow());

			foreach (var item in list)
			{
				if (_filters.Matches(item)) _table.Rows.Add(GenRow(item));
			}
		}


		public TableHeaderRow GenHeaderRow()
		{
			var thr = new TableHeaderRow();

			thr.TableSection = TableRowSection.TableHeader;

			thr.Cells.Add(GenCell("View"));
			thr.Cells.Add(GenCell("Edit"));
			thr.Cells.Add(GenCell("Delete"));

			foreach (var value in new T().ListingColumnNames)
			{
				thr.Cells.Add(GenHeaderCell(value.ToString()));
			}
			return thr;
		}

		public TableHeaderCell GenHeaderCell(string value)
		{
			var thc = new TableHeaderCell();
			thc.Text = value;
			return thc;
		}

		public TableRow GenRow(T item)
		{
			var tr = new TableHeaderRow();

			if (_hasViewPermission) tr.Cells.Add(GenCell(GenerateViewButton(item.GetPKValue())));
			if (_hasEditPermission) tr.Cells.Add(GenCell(GenerateEditButton(item.GetPKValue())));
			if (_hasDeletePermission) tr.Cells.Add(GenCell(GenerateDeleteButton(item.GetPKValue())));

			foreach (var value in item.ListingValues)
			{
				tr.Cells.Add(GenCell(value.ToString()));
			}
			return tr;
		}

		public TableRow GenRow(Control ctrl, int columnSpan)
		{
			var cell = GenCell(ctrl);

			var row = new TableRow();
			row.Cells.Add(cell);
			return row;
		}

		public TableCell GenCell(string value)
		{
			var tc = new TableCell();
			tc.Text = value;
			return tc;
		}

		public TableCell GenCell(Control ctrl)
		{
			var tc = new TableCell();
			tc.Controls.Add(ctrl);
			return tc;
		}
		#endregion buildTable

	}
}